package org.share.comm.bean;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * java bean操作类转换工具
 * 
 * @author hhm
 */
public class BeanUtils {

	/**
	 * 复制已知bean属性值到新类中对应的属性，属性大小写需一致
	 * 
	 * @param <T>
	 * @param source
	 * @param clazz
	 * @return
	 */
	public static <T> T copyProperties(Object source, Class<T> clazz) {
		T t = null;
		try {
			t = (T) clazz.newInstance();

			Field[] sourceFields = source.getClass().getFields();
			Map<String, Object> sourceMap = new HashMap<String, Object>();
			for (Field f : sourceFields) {
				try {
					if(Modifier.isFinal(f.getModifiers()) || Modifier.isStatic(f.getModifiers())){
						continue;
					}
					f.setAccessible(true);
					sourceMap.put(f.getName(), f.get(source));
				} catch (IllegalArgumentException e) {
				} catch (IllegalAccessException e) {
				}
			}
			Field[] fields = t.getClass().getFields();
			for (Field f : fields) {
				try {
					if(Modifier.isFinal(f.getModifiers()) || Modifier.isStatic(f.getModifiers())){
						continue;
					}
					f.setAccessible(true);
					if (sourceMap.containsKey(f.getName())) {
						f.set(t, sourceMap.get(f.getName()));
					}
				} catch (IllegalArgumentException e) {
				} catch (IllegalAccessException e) {
				}
			}

		} catch (InstantiationException e) {
		} catch (IllegalAccessException e) {
		}

		return t;
	}

	/**
	 * 复制已知bean属性值到新类中对应的属性，忽略属性大小写
	 * 
	 * @param <T>
	 * @param source
	 * @param clazz
	 * @return
	 */
	public static <T> T copyPropertiesIgnoreCase(Object source, Class<T> clazz) {
		T t = null;
		try {
			t = (T) clazz.newInstance();

			Field[] sourceFields = source.getClass().getFields();
			Map<String, Object> sourceMap = new HashMap<String, Object>();
			for (Field f : sourceFields) {
				try {
					if(Modifier.isFinal(f.getModifiers()) || Modifier.isStatic(f.getModifiers())){
						continue;
					}
					f.setAccessible(true);
					Object val = f.get(source);
					if(val==null)
						continue;
					sourceMap.put(f.getName().toLowerCase(), f.get(source));
				} catch (IllegalArgumentException e) {
				} catch (IllegalAccessException e) {
				}
			}
			Field[] fields = t.getClass().getFields();
			for (Field f : fields) {
				try {
					if(Modifier.isFinal(f.getModifiers()) || Modifier.isStatic(f.getModifiers())){
						continue;
					}
					f.setAccessible(true);
					if (sourceMap.containsKey(f.getName().toLowerCase())) {
						f.set(t, sourceMap.get(f.getName().toLowerCase()));
					}
				} catch (IllegalArgumentException e) {
				} catch (IllegalAccessException e) {
				}
			}

		} catch (InstantiationException e) {
		} catch (IllegalAccessException e) {
		}

		return t;
	}
	public static <T> T copyPropertiesIgnoreError(Object source, Class<T> clazz) {
		T t = null;
		try {
			t = (T) clazz.newInstance();
			
			Field[] sourceFields = source.getClass().getFields();
			Map<String, Object> sourceMap = new HashMap<String, Object>();
			for (Field f : sourceFields) {
				try {
					if(Modifier.isFinal(f.getModifiers()) || Modifier.isStatic(f.getModifiers())){
						continue;
					}
					f.setAccessible(true);
					Object val = f.get(source);
					if(val==null)
						continue;
					sourceMap.put(f.getName().toLowerCase(), f.get(source));
				} catch (IllegalArgumentException e) {
				} catch (IllegalAccessException e) {
				}
			}
			Field[] fields = t.getClass().getFields();
			for (Field f : fields) {
				try {
					if(Modifier.isFinal(f.getModifiers()) || Modifier.isStatic(f.getModifiers())){
						continue;
					}
					f.setAccessible(true);
					if (sourceMap.containsKey(f.getName().toLowerCase())) {
						f.set(t, sourceMap.get(f.getName().toLowerCase()));
					}
				} catch (IllegalArgumentException e) {
				} catch (IllegalAccessException e) {
				}
			}
			
		} catch (InstantiationException e) {
		} catch (IllegalAccessException e) {
		}
		
		return t;
	}

	/**
	 * 拷贝已知bean的属性值，到指定bean中对应的属性
	 * 
	 * @param source
	 * @param dest
	 */
	public static void copyProperties(Object source, Object dest) {
		Field[] sourceFields = source.getClass().getFields();
		Map<String, Object> sourceMap = new HashMap<String, Object>();
		for (Field f : sourceFields) {
			try {
				if(Modifier.isFinal(f.getModifiers()) || Modifier.isStatic(f.getModifiers())){
					continue;
				}
				f.setAccessible(true);
				sourceMap.put(f.getName(), f.get(source));
			} catch (IllegalArgumentException e) {
			} catch (IllegalAccessException e) {
			}
		}
		Field[] fields = dest.getClass().getFields();
		for (Field f : fields) {
			try {
				if(Modifier.isFinal(f.getModifiers()) || Modifier.isStatic(f.getModifiers())){
					continue;
				}
				f.setAccessible(true);
				if (sourceMap.containsKey(f.getName())) {
					f.set(dest, sourceMap.get(f.getName()));
				}
			} catch (IllegalArgumentException e) {
			} catch (IllegalAccessException e) {
			}
		}
	}
	
	public static Class<?> getPropertyTypeIgnoreCase(Object bean, String prop){
		Field[] fields = bean.getClass().getFields();
		Map<String, Field> fieldNameMap = new HashMap<String, Field>();
		for (Field f : fields) {
			String n = f.getName();
			fieldNameMap.put(n.toLowerCase(), f);
		}
		Field destField = fieldNameMap.get(prop.toLowerCase());
		
		return destField==null?null:destField.getType();
	}
	
	public static Class<?> getPropertyType(Object bean, String prop){
		try {
			return bean.getClass().getField(prop).getType();
		} catch (NoSuchFieldException e) {
		} catch (SecurityException e) {
		}
		
		return null;
	}

	/**
	 * 属性赋值，忽略属性大小写
	 * 
	 * @param bean
	 * @param prop
	 * @param value
	 */
	public static void setPropertyIgnoreCase(Object bean, String prop,
			Object value) {
		Field[] fields = bean.getClass().getFields();
		Map<String, Field> fieldNameMap = new HashMap<String, Field>();
		for (Field f : fields) {
			String n = f.getName();
			fieldNameMap.put(n.toLowerCase(), f);
		}

		Field destField = fieldNameMap.get(prop.toLowerCase());
		if (destField != null) {
			destField.setAccessible(true);
			try {
				destField.set(bean, value);
			} catch (IllegalArgumentException e) {
			} catch (IllegalAccessException e) {
			}
		}

	}

	/**
	 * 属性赋值，属性名需要考虑大小写
	 * 
	 * @param bean
	 * @param prop
	 * @param value
	 */
	public static void setProperty(Object bean, String prop, Object value) {
		Field destField = null;
		try {
			destField = bean.getClass().getField(prop);

			if (destField != null) {
				destField.setAccessible(true);
				try {
					destField.set(bean, value);
				} catch (IllegalArgumentException e) {
				} catch (IllegalAccessException e) {
				}
			}
		} catch (NoSuchFieldException e1) {
		} catch (SecurityException e1) {
		}
	}
	
	/**
	 * 获取类的声明属性,包括父类public属性
	 * @param obj
	 * @return
	 */
	public static Field[] getClassFields(Object obj){
		
		Set<Field> fields = new HashSet<>();
		
		//获取所有可以访问public变量,包括父类及接口中的可访问public变量
		Field[] publicFields = obj.getClass().getFields();
		for (Field field : publicFields) {
			if(Modifier.isFinal(field.getModifiers())||Modifier.isStatic(field.getModifiers())){
				continue;
			}
			fields.add(field);
		}
		//获取当前类声明的属性,不包括父类及接口中的属性
		Field[] declaredFields = obj.getClass().getDeclaredFields();
		
		for (Field field : declaredFields) {
			if(Modifier.isFinal(field.getModifiers())||Modifier.isStatic(field.getModifiers())){
				continue;
			}
			fields.add(field);
		}
		
		return fields.toArray(new Field[fields.size()]);
	}
	
}
